package com.anuo.app.study.studyjava;


import com.anuo.app.common.utils.DateUtil;
import com.anuo.app.modules.study.entity.User;
import org.apache.commons.lang3.time.DateUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {"classpath:spring/spring-context.xml"})
/**
 java 基础
 */
public class StudyBasic {


    /*
    * Java 数据类型 (分为两大类)
    * 1.基本类型 : byte , short , int , long , double , float , char , boolean
    * 2.引用类型 : class , interface , array 数组
    * */
    @Test
    public void dataType() {
        //基本类型
        byte b = 100;
        short s = 101;
        int i = 102;
        long l = 201;
        float f = 2.2f;
        double d = 123.4;
        boolean boo = false;
        char c = 't';
        //引用类型
        User user = new User();//类
        //四舍五入(一般不用这种,用BigDecimal及相关四舍五入)
        double pi = 3.14;
        long lo = Math.round(pi);

    }

    /**
     * 浮点型(包括存取货币)一般用BigDecimal , 不要用double 和 float 这两种不准确, 各种坑
     * 参考: https://examples.javacodegeeks.com/core-java/math/bigdecimal-example/
     * 复杂的金融计算参考: http://blog.csdn.net/u013066244/article/details/53172243
     */
    @Test
    public void studyBigdecimal() {
        double doubleValue = 123.4;

        //@类型转换(一般数字转BigDecimal 用 valueOf, 字符串才用 new BigDecimal)
        //这两种转换方式 new BigDecimal("字符串") 和 BigDecimal.valueOf() 是相等的

        //double 转 bigdecimal
        BigDecimal bConvert = BigDecimal.valueOf(doubleValue);
        System.out.println(bConvert);
        //int 转 bigdecimal
        int a = 3;
        BigDecimal bConvert2 = BigDecimal.valueOf(a);
        System.out.println(bConvert2);
        //string 转 bigdecimal
        String s = "123.33";
        BigDecimal bConvert3 = new BigDecimal(s);
        System.out.println(bConvert3);
        // BigDecimal to String
        String str = bConvert3.toString();
        System.out.println(str);
        //@加减乘除
        BigDecimal bigDecimal1 = BigDecimal.valueOf(16.6);
        BigDecimal bigDecimal2=BigDecimal.valueOf(3.3);
        //加
        BigDecimal add = bigDecimal1.add(bigDecimal2);
        System.out.println(add);
        //减
        BigDecimal sub = bigDecimal1.subtract(bigDecimal2);
        System.out.println(sub);
        //乘
        BigDecimal multiplyValue= BigDecimal.valueOf(2);
        BigDecimal multiply=bigDecimal1.multiply(multiplyValue);
        System.out.println(multiply);
        //除
        BigDecimal divideValue = BigDecimal.valueOf(2);
        BigDecimal divide = bigDecimal1.divide(divideValue);//一般不这么写, 一般写法见下面

        //在除的时候注意一定要保留指定位小数,不然出现无限小数会报错, 故一般除法这么写
        BigDecimal numberA=BigDecimal.valueOf(30);
        BigDecimal numberB = BigDecimal.valueOf(7);
        BigDecimal result=numberA.divide(numberB,2, RoundingMode.HALF_UP);

        //@四舍五入(可以将上面的加减乘除结果 进行四舍五入)
        //参考: https://stackoverflow.com/questions/12460482/how-to-round-0-745-to-0-75-using-bigdecimal-round-half-up
        BigDecimal result1= multiply.setScale(2, BigDecimal.ROUND_HALF_UP);//保留2位小数,并四舍五入
        System.out.println(result1);

        String val = "1.745";
        BigDecimal bigDecimalRound = new BigDecimal(val)
                .setScale(2, BigDecimal.ROUND_HALF_UP);//保留2位小数,并四舍五入
        System.out.println(bigDecimalRound);

        //@BigDecimal 比较,用compareTo 方法(返回0相等,-1小于1大于)
        BigDecimal bigA = new BigDecimal(2.35);
        BigDecimal bigB = new BigDecimal(2.34);
        if (bigA.compareTo(bigB) == 1) {
            System.out.println("bigA greater than bigB ");
        }
        //@格式化输出
        BigDecimal formatValue=BigDecimal.valueOf(965698649);
        NumberFormat numberFormat=NumberFormat.getCurrencyInstance(Locale.CHINA);
        System.out.println(numberFormat.format(formatValue));


    }



    //数据类型值比较
    @Test
    public void studyCompare() {
        //string 比较
        String s1 = "a";
        String s2 = "a";
        char chA = 'b';
        char chB = 'b';
        boolean booStr = s1.equals(s2);

        //整型 比较
        int iA = 1;
        int iB = 1;
        Integer itA = new Integer(2);
        Integer itB = new Integer(2);
        boolean boo1 = iA == iB;//true
        boolean boo2 = itA == itB;//false
        boolean boo3 = itA.equals(itB);//true
        boolean boochar = chA == chB;//true



        //浮点型double 比较
        //一般用 >,<,==比较没问题,如下代码
        double dA = 2.1;
        double dB = 2.3;
        if (dA == dB) {
            System.out.println("dAdB equals");
        }
        if (dA < dB) {
            System.out.println(("dA less than dB "));
        }

        //这样比较必定出问题(坑)
        double dC = 0.1 * 3;
        double dD = 0.3;
        if (dC == dD) {//这里永远为false
            System.out.println("dCdD equals");
        }

        //改成这样就对了, so 平时使用尽量用 BigDecimal 来代替 double
        BigDecimal bigC1 = BigDecimal.valueOf(0.1);
        BigDecimal bigC2 = BigDecimal.valueOf(3);
        BigDecimal bigC = bigC1.multiply(bigC2);
        BigDecimal bigD = BigDecimal.valueOf(0.3);
        if (bigC.compareTo(bigD) == 0) {
            System.out.println("bigC bigD equals");
        }

        //BigDecimal 比较用 compareTo 方法(返回0相等,-1小于,1大于)
        BigDecimal bigA = new BigDecimal(2.35);
        BigDecimal bigB = new BigDecimal(2.34);
        if (bigA.compareTo(bigB) == 1) {
            System.out.println("bigA greater than bigB ");
        }

    }

    //常见数据类型转换
    @Test
    public void studyConvert() throws ParseException {
        //强制转换
        int i = 100;
        byte b = (byte) i;
        /*
          number 和 String 的转换
          number to string   number包装类型.toString(number)
          string to number   number包装类型.parse包装类型(string)
          例子如下:
         */
        //int 和 String 的转换
        String s = Integer.toString(i);
        int inew = Integer.parseInt(s);
        //double 和 string 的转换
        double d = 9.2;
        String dstr = Double.toString(d);
        double dd = Double.parseDouble(dstr);



    }

    //常量
    public static final double PI = 3.14; //通常大写字母表示常量


    //数组
    @Test
    public void StudyArray() {
        String[] strArray = new String[9];//不赋初始值
        String[] array2 = {"f", "u", "c"};//赋初始值
        //对数组进行操作用Arrays 类
        Arrays.toString(strArray);

    }

    /*日期处理
    *Date vs Calendar
    *1.简单日期用 Date 处理
    *2.日期加减,设置等用Calendar
    *当自带的api 不能满足时用 joda: so 大量推荐的库  http://www.joda.org/joda-time/
    * */
    @Test
    public void studyDateTime() throws ParseException {
        //日期和字符串的转换
        //date to String
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date currentTime = Calendar.getInstance().getTime();
        String dateStr = df.format(currentTime);
        System.out.println(dateStr);
        //String to date
        String strDate = "2017-05-11 17:55:30";
        Date date = df.parse(strDate);
        System.out.println(date);
        System.out.println(df.format(date));
        //创建一个代表2009年6月12日的Calendar对象
        Calendar c1 = Calendar.getInstance(); //获取当前时间
        c1.set(2009, 6 - 1, 12);//设置日期


        //获取年月日
        int year = c1.get(Calendar.YEAR); // 获得年份
        int month = c1.get(Calendar.MONTH) + 1; // 获得月份
        int dateNumber = c1.get(Calendar.DATE); // 获得日期

        //日期加减
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 5);
        calendar.add(Calendar.DATE, -5);

        //统计执行时间
        long beginTime = System.nanoTime();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        long endTime = System.nanoTime();

        long duration = (endTime - beginTime) / 1000000;//divide by 1000000 to get milliseconds.
        System.out.println(duration);

        //日期比较
        Date date1 = DateUtil.strToDate("2017-12-20");
        Date date2 = DateUtil.strToDate("2017-12-21");
        if (date1.before(date2)) {
            System.out.println("date1 less than date2");
        }
        if (date1.after(date2)) {
            System.out.println("date1 greater than date2");
        }
        if (date1.equals(date2)) {
            System.out.println("date1 equals date2");
        }

    }

    //可变参数(就是一个参数接收多个传入值)
    @Test
    public void studyParams() {
//        public static void main(String args[]) {
//            // 调用可变参数的方法
//            printMax(34, 3, 3, 2, 56.5);
//            printMax(new double[]{1, 2, 3});
//        }
//
//        public static void printMax( double... numbers) {
//            if (numbers.length == 0) {
//                System.out.println("No argument passed");
//                return;
//            }
//
//            double result = numbers[0];
//
//            for (int i = 1; i <  numbers.length; i++){
//                if (numbers[i] >  result) {
//                    result = numbers[i];
//                }
//            }
//            System.out.println("The max value is " + result);
//        }
    }

    /**
     * 运算符计算
     */
    @Test
    public void calculate() {
        //double 计算
        double a = 12.4;
        double b = 1;
        a = b * (a / 2);
        System.out.println(Double.toString(a));
        //BigDecimal 计算
        BigDecimal c = new BigDecimal(12.6);
        BigDecimal d = new BigDecimal(1);
        c = d.multiply((c.divide(new BigDecimal(2))));
        System.out.println(c);


    }




}
